package com.example.erp;

import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.RequestParam;
import reactor.core.publisher.Flux;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @Author: jiang
*/

@RestController
@RequestMapping("/openai/client")
public class OpenAiChatClientController {

	private static final String DEFAULT_PROMPT = "你好，介绍下你自己！";

	private final ChatClient openAiChatClient;

	public OpenAiChatClientController(ChatModel chatModel) {
		// 构造时，可以设置 ChatClient 的参数
		// {@link org.springframework.ai.chat.client.ChatClient};
		this.openAiChatClient = ChatClient.builder(chatModel)
				// 实现 Chat Memory 的 Advisor
				// 在使用 Chat Memory 时，需要指定对话 ID，以便 Spring AI 处理上下文。
				.defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build())
				// 实现 Logger 的 Advisor
				.defaultAdvisors(new SimpleLoggerAdvisor())
				// 设置 ChatClient 中 ChatModel 的 Options 参数
				.defaultOptions(OpenAiChatOptions.builder()
						.topP(0.7)
						.build()
				).build();
	}

	// 也可以使用如下的方式注入 ChatClient
	// public OpenAIChatClientController(ChatClient.Builder chatClientBuilder) {
	//  	this.openAiChatClient = chatClientBuilder.build();
	// }

	/**
	 * ChatClient 简单调用，执行默认提示语的 AI 生成请求
	 */
	@GetMapping("/simple/chat")
	public String simpleChat() {
		return openAiChatClient.prompt(DEFAULT_PROMPT).call().content();
	}

	/**
	 * ChatClient 流式调用，调用流式生成接口 - 支持实时获取生成过程的分块响应
	 */
	@GetMapping("/stream/chat")
	public Flux<String> streamChat(HttpServletResponse response) {
		response.setCharacterEncoding("UTF-8");
		return openAiChatClient.prompt(DEFAULT_PROMPT).stream().content();
	}

	/**
	 * ChatClient 流式响应
	 */
	@GetMapping(value = "/stream/response", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
	public Flux<ServerSentEvent<String>> simpleChat(@RequestParam String message) {
		return openAiChatClient.prompt()
				.user(message)
				.stream()
				.content()
				.map(content -> ServerSentEvent.<String>builder()
						.data(content)
						.build());
	}

}